How it's wired Tepna
← the -Dex suite · node wiring

🟢PpgDex

PpgDex is ECGDex’s optical twin — it senses one signal, the raw photoplethysmogram, finds each pulse, and from the interval series produces the same HRV family plus something neither ECG nor oximetry can: pulse-wave morphology.

Signal sensed
Raw PPG (optical)+ ACC / GYRO motion channels
Device
Polar Verity Sensearmband · via Polar Sensor Logger
Input format
Multi-file Polar Sense setPPG + ACC/GYRO/PPI/MARKER
Produces
HRV + pulse morphology→ ganglior.node-export
01 — WHAT IT'S FOR

A single-signal receptor

Read the suite as a reflex arc: receptors → relay → integration → insight. PpgDex is an afferent receptor — it does exactly one transduction well and reports inward. It never reaches into another node; cross-signal work happens only through the Ganglior export, consumed by the Integrator.

🧠
One signal per node. PpgDex senses raw ppg (optical) and nothing else. If you’re tempted to sense a second signal, that’s a second node — fusion is the Integrator’s job, never a receptor’s.
02 — THE WIRING

The file stack

PpgDex is built from external *.js files referenced by PpgDex.src.html and bundled to a standalone PpgDex.html. Dependencies point downhill only — UI → DSP → Core — and each file owns exactly one job. Edit the .js + .src.html, never the bundle; re-bundle after changes.

DSP
ppgdex-dsp.jsDSP
Raw wrist-PPG → systolic feet/peaks → PP intervals → HRV. Optical beat detection (soft upstroke — not Pan–Tompkins) and the ACC+GYRO motion gate, the signature feature. Exposes window.PPGDSP.
ppgdex-morph.jsDSP
Pulse-wave morphology from a clean median pulse: rise/crest time, dicrotic-notch detection, augmentation & reflection indices, pulse width, perfusion index. The optical analog of ECG’s QRS/QT block.
ppgdex-profile.jsDSP
ANS-readiness + ANS-age fed by PPI-derived HRV, with perfusion index surfaced as a readiness subscore. No BP/PTT — single-site wrist PPG cannot estimate them.
Core
kernel-constants.jsCore · shared
The frozen physiology kernel — one source of truth for every cross-fleet threshold, plus a content-derived hash stamped into each export so two bundles built on different rulebooks can’t silently “agree” when fused.
ganglior-provenance.jsCore · shared
Loaded first — installs the read-hook that makes every export attributable to the exact code + inputs that produced it (the buildHash provenance stamp). 100% local.
metric-registry.jsCore · shared
The shared half of the evidence system: the badge SHAPE, depth tiering and the injected badge CSS. The per-node registry below supplies the DATA, so a Validated dot looks identical in every node.
crossnight-envelope.jsCore · shared
The shared, versioned shape (ganglior.crossnight v1.0) every node emits and the Integrator reads — the container, not the math (the local crossNight() stats stay per-node).
ppgdex-registry.jsCore
Per-metric DATA map; labels mirror render + cross defs. Time-domain HRV grades validated; morphology indices grade emerging.
Render · UI
ppgdex-render.jsRender · UI
PPGScope canvas (min/max envelope pyramid, peak + foot markers, greyed motion/SQI spans) plus SVG charts: PPI tachogram, Poincaré, motion ribbon, median-pulse morphology overlay, epoch trends. Exposes window.PPGUI.
App · glue
ppgdex-app.jsApp · glue
Multi-file Polar Sense ingest (PPG + companion ACC/GYRO/PPI/MARKER), a multi-session model keyed by floating t0Ms, pipeline, UI population and v2.0 exports.
Fusion · export
ppgdex-cross.jsFusion · export
The byte-identical multi-session analytics helper.
🕒
The Clock Contract. PpgDex stamps every record as floating wall-clock tMs (local civil time encoded as if UTC) and reads it back with getUTC* — so the recording reads identically in any viewer’s timezone, and two devices recording the same minute land on the same tMs. parseTimestamp is duplicated locally by design.
03 — HOW IT'S ACHIEVED

From file drop to Ganglior event

The pipeline is the same shape across the suite: ingest → parse on the canonical clock → compute in DSP → grade & render in UI → emit onto the bus. No number is computed in the render layer; it asks DSP for the value and the registry for how to show it.

Load the Polar Sense set

Drop the multi-file export — PPG plus its companion ACC/GYRO/PPI/MARKER files. Sessions are keyed by floating t0Ms.

ppgdex-app.js → multi-file ingest

Detect optical beats

A soft-upstroke detector (Pan–Tompkins does not apply to PPG) finds systolic feet and peaks, yielding the PP interval series.

ppgdex-dsp.js → beat detect

Gate on motion

The ACC+GYRO motion gate — the signature feature — excludes movement-corrupted spans before HRV, since wrist optics are motion-sensitive.

ACC+GYRO motion gate

HRV + morphology

Clean PPI drives the HRV suite; morph.js extracts rise time, dicrotic notch, augmentation/reflection indices and perfusion from the median pulse.

ppgdex-dsp.js + ppgdex-morph.js

Emit onto Ganglior

Export the node-export JSON. The wrist↔fingertip PTT that PPG alone can’t do is left to the Integrator.

ganglior.node-export
04 — HOW MUCH TO TRUST IT

The evidence ladder

Every metric PpgDex surfaces carries an evidence grade — a non-hue badge whose fill is the confidence ladder: solid bullseye for a raw reading, down to a dashed ring for a friendly estimate. A measurement and a projection must never look alike. Grades live in ppgdex-registry.js, the one source of truth.

Measured Pulse HR · perfusion index · rise time · coverage & quality
Validated Time-domain HRV from PPI — rMSSD · SDNN · SD1 / SD2
Emerging Augmentation index · reflection index · dicrotic-notch morphology
Experimental Composite stability from optical HRV
Heuristic ANS-age · VO₂max estimate
05 — LIMITATIONS & CONSIDERATIONS

What it can and can't say

Honesty is architectural: a guess is never dressed as a measurement, a missing value stays null rather than fabricated, and confidence is kept separate from signal quality. The node-specific caveats:

Optical detection differsnote

PPG has a soft upstroke, not a sharp QRS — so it uses a foot/peak detector, not Pan–Tompkins. The downstream HRV, once you have intervals, is identical to ECG’s.

Motion is the enemycaution

Wrist optics corrupt easily under movement; the ACC+GYRO gate is mandatory, and excluded spans are shown greyed rather than guessed.

No BP / PTT from one sitelimitation

A single optical site cannot derive pulse-transit-time or blood pressure. That cross-site fusion lives in the Integrator, never faked here.

Morphology is the bonusby design

Augmentation, reflection and perfusion indices are something neither OxyDex nor ECGDex can produce — graded emerging because they are device-dependent.

06 — HOW TO USE IT

For the curious, and for the next coder

📂

Open the instrument

PpgDex is one self-contained file. Open PpgDex.html in any browser — online, offline, or from file://. Nothing installs, nothing phones home.

Open PpgDex →
📥

Drop your recording

Drag a Polar Verity Sense export (multi-file polar sense set) onto the upload zone. It’s read in-browser and turned into metrics on your device alone.

🎚️

Read at your depth

Start in Core for the headline readiness and a plain-language line. Step up to Advanced for full tables and charts, or Research for composites and the full dump. Each metric’s evidence dot tells you how far to trust it.

🔀

Export onto Ganglior

Export a ganglior.node-export JSON to feed the Integrator, or to upgrade a peer node’s read. Events carry a wall-clock t; consumers reconstruct absolute time from the recording start.

PpgDex reference guide →
🛠️

If you’re changing it

Edit the ppgdex-*.js files or PpgDex.src.htmlnever the bundled PpgDex.html — then re-bundle. Run Dex-Test-Suite.html until all-green, and verify-provenance.html after re-bundling.